﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Net.Chirash.Twitter.TwitterClient;

namespace Net.Chirash.Twitter.TwitterClient.DBSyncronize
{
    public abstract class TaskBase
        : IEquatable<TaskBase>
    {
        public string TaskName { get; private set; }

        public TaskBase(string taskname)
        {
            this.TaskName = taskname;
        }

        public abstract void DoTask(object arg);
        public abstract bool IsObserved { get; }

        public static bool operator ==(TaskBase A, TaskBase B) { return A.TaskName == B.TaskName; }
        public static bool operator !=(TaskBase A, TaskBase B) { return !(A == B); }
        public bool Equals(TaskBase other)
        {
            return this == other;
        }
    }

    public abstract class ObservableTaskBase<T>
        : TaskBase, IObservable<T>
    {

        #region Constructor

        public ObservableTaskBase(string taskname)
            : base(taskname)
        {
        }

        #endregion

        protected virtual void NotifyRefreshStart()
        {
            foreach (var task in observerList.ToArray())
                if (task is ITaskObserver<T>)
                    (task as ITaskObserver<T>).OnRefreshStart();
        }

        protected virtual void NotifyRefreshEnd()
        {
            foreach (var task in observerList.ToArray())
                if (task is ITaskObserver<T>)
                    (task as ITaskObserver<T>).OnRefreshEnd();
        }

        protected virtual void NotifyCompleted()
        {
            foreach (var task in observerList.ToArray())
                task.OnCompleted();
        }

        protected virtual void NotifyNext(T data)
        {
            foreach (var task in observerList.ToArray())
                task.OnNext(data);
        }

        protected virtual void NotifyError(Exception ex)
        {
            foreach (var task in observerList.ToArray())
                task.OnError(ex);
        }

        public override bool IsObserved
        {
            get { return this.observerList.Count > 0; }
        }

        #region Implemention of IObservable

        private List<IObserver<T>> observerList = new List<IObserver<T>>();
        public IDisposable Subscribe(IObserver<T> observer)
        {
            observerList.Add(observer);

            return new UnSubscriber<T>(this.observerList, observer);
        }

        #region UnSubscriber class
        private class UnSubscriber<TypeData>
            : IDisposable
        {
            private IList<IObserver<TypeData>> observerList;
            private IObserver<TypeData> observer;

            public UnSubscriber(IList<IObserver<TypeData>> list, IObserver<TypeData> observer)
            {
                this.observerList = list;
                this.observer = observer;
            }

            public void Dispose()
            {
                if (observer != null && observerList.Contains(observer))
                    observerList.Remove(observer);
            }
        }
        #endregion

        #endregion
    }

    public interface ITaskObserver<in T>
        : IObserver<T>
    {
        void OnRefreshStart();
        void OnRefreshEnd();
    }
}
